package com.mycode.flyweight12;

import com.mycode.flyweight12.resolve.Coordinates;
import com.mycode.flyweight12.resolve.IgoChessman;
import com.mycode.flyweight12.resolve.IgoChessmanFactory;

/**
 * 享元模式：运用共享技术有效地支持大量细力度对象的复用，系统只使用少量的对象，实现对象的多次复用，该模式要求额能够共享的对象必须是细粒度对象
 *          享元模式能做到共享的关键是区分了 内部状态 和 外部状态。
 *          内部状态：存储在享元对象内部，并且不会随环境改变而改变的状态，内部状态可以共享
 *          外部状态：随环境改变而改变的、不可以共享的状态
 *
 * 标准的享元模式结构中既包含可以共享的具体享元类，也包含不可以共享的非共享具体享元类，但是也有两种特殊的享元模式：单纯享元模式 和 复合享元模式
 *     单纯享元模式：所有的具体享元类都是可以共享的，不存在非共享具体享元类
 *     复合享元模式：将一些单纯享元对象使用组合模式加以组合，复合享元对象本身不能共享，但是可以分解成单纯享元对象。
 * 主要优点：
 *     1、可以极大减少内存中对象的数量，使得相同或相似对象在内存中只保存一份，从而节约系统资源，提高系统性能
 *     2、享元模式外部状态相对独立，而且不会影响其内部状态，从而使得享元对象可以在不同环境中被共享
 * 主要缺点：
 *     1、享元模式使得系统变得复杂，需要分离出内部状态和外部状态，程序逻辑复杂化
 *     2、需要部分状态外部化，读取外部状态使得运行时间变长
 * 使用场景：
 *     1、系统有大量相同或相似对象，造成内存的大量耗费
 *     2、对象的大部分状态都可以外部化，可以将这个外部状态传入对象中
 *     3、享元模式需要维护一个存储享元对象的享元池，这需要耗费一定的系统资源
 */
public class Bootstrap {

    public static void main(String[] args) {
        String string = new String("aaaa");

        String string3 = "aaaa";

        String string2 = new String("aaaa");

        System.out.println(string == string2);
        System.out.println(string == string3);
        System.out.println(string2 == string3);


        // IgoChessmanFactory factory = IgoChessmanFactory.getInstance();
        //
        // IgoChessman black1 = factory.getIgoChessman("b");
        // IgoChessman black2 = factory.getIgoChessman("b");
        // System.out.println("判断两颗黑子是否相同：" + (black1 == black2));
        //
        // IgoChessman white1 = factory.getIgoChessman("w");
        // IgoChessman white2 = factory.getIgoChessman("w");
        // System.out.println("判断两颗白子是否相同：" + (white1 == white2));
        // black1.display();
        // black2.display();
        // white1.display();
        // white2.display();
        //
        // System.out.println("-------------------------------");
        // black1.display(new Coordinates(1, 2));
        // black2.display(new Coordinates(3, 4));
        // white1.display(new Coordinates(2, 5));
        // white2.display(new Coordinates(2, 4));
    }
}
